package com.fuce.xiaoai.Util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.digest.DigestUtil;

public class SinVerificationUtil {

	public String key_group = "382914476631918600";
	public String keyId = "abcde";
	public String secretKey = "xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyy";//
	public String miaiSignVersion = "MIAI-HmacSHA256-V1";// 小米签名版本
	public String urlPath = "/hmac/testGet";
	public String xiaomiDate = "Mon, 7 Aug 2017 08:00:50 GMT";// new Date().toString();
	public String host = "localhost:19001";
	
	
	
	/**
	 * get文本签名
	 * @param queryParams
	 * @param xiaomiDate
	 * @param host
	 * @return
	 */
	public  String generateGetTextToSign(Map<String, String> queryParams, String xiaomiDate, String host) {
		return generateTextToSign("GET", "/hmac/testGet", canonicalizeParams(queryParams), xiaomiDate, host, "", "");
	}
	
	/**
	 * post方法文本签名
	 * @param formParams
	 * @param xiaomiDate
	 * @param host
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public  String generatePostTextToSign(Map<String, String> formParams)
			throws UnsupportedEncodingException {

		byte[] body = canonicalizeParams(formParams).toString().getBytes("utf-8");

		String contentMD5 = Base64.encode(DigestUtil.md5(body));

		return generateTextToSign("POST", "/hmac/testPost", "", xiaomiDate, host, "application/x-www-form-urlencoded",
				contentMD5);

	}
	
	
	/**
	 * 签名文本
	 * @param method
	 * @param urlPath
	 * @param canonParam
	 * @param xiaomiDate
	 * @param host
	 * @param contentType
	 * @param contentMD5
	 * @return
	 */
	public static String generateTextToSign(String method, String urlPath, String canonParam, String xiaomiDate,
			String host, String contentType, String contentMD5) {

		return new StringBuilder().append(method).append('\n') // 1. Http Method
				.append(urlPath).append('\n') // 2. URL Path
				.append(canonParam).append('\n') // 3. 规范化的 query params
				.append(xiaomiDate).append('\n') // 4. X-Xiaomi-Date
				.append(host).append('\n') // 5. Host
				.append(contentType).append('\n') // 6. Content-Type
				.append(contentMD5).append('\n') // 7. Content-MD5
				.append("") // 8. 对其他的需要的 Header 进行规范化
				.toString();
	}

	/**
	 * 编译参数
	 * @param map
	 * @return
	 */
	public  String canonicalizeParams(Map<String, String> map){
		if (map == null) {
			return "";
		}
		StringBuffer sb = new StringBuffer();
		List<String> keys = new ArrayList<String>(map.keySet());
		if (true) {
			Collections.sort(keys);
		}
		for (int i = 0; i < keys.size(); i++) {
			String key = (String) keys.get(i);
			String value = map.get(key).toString();
			sb.append(key + "=" + value);
			sb.append("&");
		}
		String s = sb.toString();
		if (s.endsWith("&")) {
			s = s.substring(0, s.lastIndexOf("&"));
		}
		return s;
	}

	/**
	 * 通用授权
	 * @param secretKey
	 * @param textToSign
	 * @return
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws IllegalStateException
	 * @throws UnsupportedEncodingException
	 */
	public  String generateAuthorization( String textToSign)
			throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException {
		String signature = generateSign(textToSign);
		return signature;
	}
	
	/**
	 * 签名
	 * @param secretKey
	 * @param textToSign
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @throws IllegalStateException
	 * @throws UnsupportedEncodingException
	 */
	public  String generateSign(String textToSign)
			throws NoSuchAlgorithmException, InvalidKeyException, IllegalStateException, UnsupportedEncodingException {

		SecretKeySpec signingKey = new SecretKeySpec(Base64.decode(secretKey), "HmacSHA256");
		Mac mac = Mac.getInstance("HmacSHA256");
		mac.init(signingKey);
		byte[] bytes = mac.doFinal(textToSign.getBytes("UTF-8"));
		return HexUtil.encodeHexStr(bytes);
	}

}
